//
//  PlayerFighter.cpp
//  airfight
//
//  Created by aaron more on 12-8-24.
//  Copyright (c) 2012年 moonriver. All rights reserved.
//

#include <iostream>
#include "PlayerFighterSprite.h"
#include <math.h>
#include "CCActionIntervalEx.h"
#include "BattleActionLayer.h"

PlayerFighterSprite::PlayerFighterSprite()
: m_pFighterId(0)
, m_pBlood(0)
, m_pArmor(0)
, m_pSpeed(0)    
, m_iTouches(0)
, m_IFrameIndex(0)
, bullet_baseTag(10000)
, bullet_idxTag(10000)
, bouns_BaseTag(9000000)
{

}

PlayerFighterSprite::~PlayerFighterSprite()
{
    CCLog("player ~~~~~");
    CC_SAFE_RELEASE(m_pBulletDictionary);
}

bool PlayerFighterSprite::init()
{
    EntitySprite::init();
    m_pBulletDictionary = CCDictionary::create();
    m_pBulletDictionary->retain();
    
    toRedrawBullets = CCArray::create();
    toRedrawBullets->retain();
    
    return true;
}

void PlayerFighterSprite::onEnter()
{
    EntitySprite::onEnter();
    batch = (CCSpriteBatchNode*)this->getParent(); 
    CCDictElement* pElement = NULL;
    CCDICT_FOREACH(m_pBulletDictionary, pElement)
    {
        BulletNode *node = (BulletNode*)pElement->getObject();
        CCArray *bullets = node->getBulltes();
        CCObject *bulletSprite = NULL;
        int bulletTag = node->getBaseTag();
        CCARRAY_FOREACH(bullets, bulletSprite)
        {
            BulletSprite *m_bulletSprite = (BulletSprite*)bulletSprite;
            m_bulletSprite->setVisible(false);

            int tag  = ++bulletTag;
            m_bulletSprite->setTag(tag);
            batch->addChild(m_bulletSprite,BULLET_DEPTH,tag);
            m_bulletSprite->release();
        }
    }
    CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(PlayerFighterSprite::redrawBulletContact), REDRAW_BULLET_CONTACT_NOTIFICATION, NULL);
    CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(PlayerFighterSprite::redrawBulletOutbound), REDRAW_BULLET_OUTBOUND_NOTIFICATION, NULL);
    
    scheduleUpdate();
}

void PlayerFighterSprite::setBullets(int p_id,BulletNode *node)
{   
    m_pBulletDictionary->setObject(node,p_id);
}


void PlayerFighterSprite::handleContact(ENTITY_TYPE type, CCDictionary *effect)
{
    if(this->m_pBlood <= 0)
    {
        return;
    }
    switch (type) {
        case ENEMY_FIGHTER:
        {
            int damage = ((CCInteger*)effect->objectForKey("damage"))->getValue();
            CCInteger* tag = (CCInteger*)effect->objectForKey("tag");
            if(this->m_pBlood - damage > 0 ) //敌机血少
            {
                this->m_pBlood -= damage;
                CCNotificationCenter::sharedNotificationCenter()->postNotification(CHANGE_PROFILE_NOTIFICATION, CCInteger::create(this->m_pBlood));
                CCNotificationCenter::sharedNotificationCenter()->postNotification(ENEMY_EXPLOSION_NOTIFICATION, tag);
            }
            else //小飞机血少
            {
                this->m_pBlood = 0;
                CCNotificationCenter::sharedNotificationCenter()->postNotification(PLAYER_EXPLOSION_NOTIFICATION,NULL);
            }
            break;
        }
        case ENEMY_BULLET:
        {
            int damage = ((CCInteger*)effect->objectForKey("damage"))->getValue();
            CCInteger* tag = (CCInteger*)effect->objectForKey("tag");
            if(this->m_pBlood - damage > 0 ) 
            {
                this->m_pBlood -= damage;
                CCNotificationCenter::sharedNotificationCenter()->postNotification(CHANGE_PROFILE_NOTIFICATION, CCInteger::create(this->m_pBlood));
                CCDictionary *dict = CCDictionary::create();
                dict->setObject(tag, "tag");
                dict->setObject(CCInteger::create(ENEMYBULLET_DESTROY_COLLISION), "type");
                CCNotificationCenter::sharedNotificationCenter()->postNotification(DESTROY_BULLET_NOTIFICATION, dict);
            }
            else
            {
                this->m_pBlood = 0;
                CCNotificationCenter::sharedNotificationCenter()->postNotification(PLAYER_EXPLOSION_NOTIFICATION,NULL);
            }

            break;
        }
        default:
            break;
    }
    
}

void PlayerFighterSprite::redrawBulletContact(CCInteger* tag)
{
    
    BulletSprite* bullet = (BulletSprite*)BattleActionLayer::getInstance()->m_SpriteBatch->getChildByTag(tag->getValue());
    BattleActionLayer::getInstance()->m_PlayerFighterSprite->toRedrawBullets->addObject(bullet);
    
    CCNotificationCenter::sharedNotificationCenter()->postNotification(PLAYERBULLET_EXPLOSION_ANIMATION_NOTIFICATION, tag);
    //bullet->release();

//    CCPoint curr_playerFighterPoint = this->getPosition();
//    CCPoint bulletFirePoint = bullet->getFirePoint();
//    bullet->setPosition(ccp(curr_playerFighterPoint.x+bulletFirePoint.x,curr_playerFighterPoint.y+bulletFirePoint.y));
}

void PlayerFighterSprite::redrawBulletOutbound(CCInteger* tag)
{
    BulletSprite* bullet = (BulletSprite*)(BattleActionLayer::getInstance()->m_SpriteBatch->getChildByTag(tag->getValue()));
    BattleActionLayer::getInstance()->m_PlayerFighterSprite->toRedrawBullets->addObject(bullet);
}

void PlayerFighterSprite::update(float dt)
{
    if(this->getToDestroyFlag() != 0)
    {
        b2Body *destroyPlayerBody = this->getPhysicsBody();
        destroyPlayerBody->SetActive(false);
        destroyPlayerBody->GetWorld()->DestroyBody(destroyPlayerBody);
        this->stopAllActions();
        this->cleanup();
        switch (this->getToDestroyFlag()) {
            case PLAYER_DESTROY_DIE:
            {
                CCNotificationCenter::sharedNotificationCenter()->postNotification(PAYOFF_SCENEN_NOTIFICATION, CCInteger::create(PAYOFF_DIE));
                break;
            }
            case PLAYER_DESTROY_SUCCESS:
            {
                CCNotificationCenter::sharedNotificationCenter()->postNotification(PAYOFF_SCENEN_NOTIFICATION, CCInteger::create(PAYOFF_PASS));
                break;
            }
            default:
                break;
        }
        return;
    }
    
    //回收子弹
    CCObject *redrawBulletObject = NULL;
    CCARRAY_FOREACH(toRedrawBullets, redrawBulletObject)
    {
        CC_BREAK_IF(!redrawBulletObject);
        BulletSprite* redrawBullet = (BulletSprite*)redrawBulletObject;
        if(redrawBullet->isVisible())
        {
            b2Body *destroyBulletBody = redrawBullet->getPhysicsBody();
            this->getPhysicsBody()->GetWorld()->DestroyBody(destroyBulletBody);
            redrawBullet->setPhysicsBody(NULL);
            redrawBullet->setVisible(false);
            redrawBullet->stopAllActions();
            redrawBullet->setPosition(ccp(0,0));
        }
       
    }
    toRedrawBullets->removeAllObjects();
    
    
    m_IFrameIndex++;
    CCDictElement* pElement = NULL;
    CCDICT_FOREACH(m_pBulletDictionary, pElement)
    {
        BulletNode *node = (BulletNode*)pElement->getObject();
        int frequency = node->getFrequency();
        int bulletCount = node->getBulletCount();
        int idx = node->getBaseTag();
        if( 0 == m_IFrameIndex % frequency )
        {
            CCPoint curr_playerFighterPoint = this->getPosition();
            
            BulletSprite *m_bulletSprite = NULL;
            b2BodyDef playerBulletBodyDef;
            playerBulletBodyDef.type = b2_dynamicBody;
            playerBulletBodyDef.position = b2Vec2(curr_playerFighterPoint.x/PTM_RATIO,curr_playerFighterPoint.y/PTM_RATIO);
            playerBulletBodyDef.bullet = true;
            do {
                m_bulletSprite = (BulletSprite*)batch->getChildByTag(++idx);
                if(NULL != m_bulletSprite && !m_bulletSprite->isVisible())
                {
                    CCPoint bulletFirePoint = m_bulletSprite->getFirePoint();
                    m_bulletSprite->setPosition(ccp(curr_playerFighterPoint.x+bulletFirePoint.x,curr_playerFighterPoint.y+bulletFirePoint.y));
                   
                    playerBulletBodyDef.userData = m_bulletSprite;
                    b2Body *playerBulletBody = (this->getPhysicsBody()->GetWorld())->CreateBody(&playerBulletBodyDef);
                    playerBulletBody->SetActive(true);
                    
                    CCSize bulletContentSize = m_bulletSprite->getContentSize();
                    b2PolygonShape playerBulletDynamicBox;
                    playerBulletDynamicBox.SetAsBox(bulletContentSize.width * 0.1 / PTM_RATIO, bulletContentSize.height * 0.1 / PTM_RATIO,b2Vec2(CCPointZero.x/PTM_RATIO,CCPointZero.y/PTM_RATIO),0);
                    b2FixtureDef playerBulletFixtureDef;
                    playerBulletFixtureDef.shape = &playerBulletDynamicBox;
                    playerBulletFixtureDef.density = 0.0f;
                    playerBulletFixtureDef.friction = 0.0f;
                    playerBulletFixtureDef.filter.groupIndex = FILTER_PLAYER_GROUPINDEX;
                    playerBulletFixtureDef.filter.categoryBits = FILTER_PLAYERBULLET_CATEGORYBITS;
                    playerBulletFixtureDef.filter.maskBits = FILTER_PLAYERBULLET_MASKBITS;
                    playerBulletBody->CreateFixture(&playerBulletFixtureDef);
                    m_bulletSprite->setPhysicsBody(playerBulletBody);
                    m_bulletSprite->setVisible(true);
                        
                    int moveType = m_bulletSprite->getType();
                    int speed = m_bulletSprite->getSpeed();
                    float duration = m_bulletSprite->getDuration();
                    int angle = m_bulletSprite->getAngle();
                    m_bulletSprite->setRotation(angle);
                    switch (moveType) {
                        case 1:
                        {
                            float deltX = speed*sin(angle*PI/180); 
                            float deltY = speed*cos(angle*PI/180);
                            CCActionInterval *actionBy = CCMoveBy::create(duration, CCPointMake(deltX,deltY));   
                            m_bulletSprite->runAction( CCRepeatForever::create(actionBy));
                            break;
                        }
                        default:
                            break;
                     
                    }
                    //
                    //CCLog("rf = %d",m_bulletSprite->retainCount());
                    //m_bulletSprite->release();
                    break;
                }
                
            } while (--bulletCount);
        }
    }
    
    //position
    int leftdisX = m_AimLocation.x - getPosition().x;
    int leftdisY = m_AimLocation.y - getPosition().y;
    
    if(1 == m_iTouches)
    {
        double angle = atan(fabs((float)leftdisY)/fabs((float)leftdisX));
        float speedX = 0.0f, speedY = 0.0f;
        
        speedX = m_pSpeed * cos(angle);
        speedY = m_pSpeed * sin(angle);
        
        speedX = fabs(speedX) < fabs(leftdisX)? fabs(speedX) : fabs(leftdisX);
        speedX = leftdisX > 0? speedX : -speedX;
        
        speedY = fabs(speedY) < fabs(leftdisY)? fabs(speedY) : fabs(leftdisY);
        speedY = leftdisY > 0? speedY : -speedY;
        
        int newX = getPosition().x + speedX;
        int newY = getPosition().y + speedY;
        
        newX = newX >= 0? newX : 0;
        newX = newX <= 320? newX : 320;
        
        newY = newY >= getContentSize().height/2? newY : getContentSize().height/2;
        newY = newY <=480 - getContentSize().height/2? newY : 480 - getContentSize().height/2;
        
        setPosition(ccp(newX, newY));
    }
}

void PlayerFighterSprite::touchesBegan(CCSet* touches, CCEvent* event) 
{
    m_iTouches++;
    CCTouch *touch = (CCTouch*)touches->anyObject(); 
    m_InitTouch = touch->locationInView();
    m_InitTouch = CCDirector::sharedDirector()->convertToGL(m_InitTouch);
    
    m_CurTouch = m_InitTouch;
    m_InitLocation = getPosition();
    m_AimLocation = getPosition();
}

void PlayerFighterSprite::touchesMoved(CCSet* touches, CCEvent* event) 
{
    CCTouch *touch = (CCTouch*)touches->anyObject(); 
    m_CurTouch = touch->locationInView();
    m_CurTouch = CCDirector::sharedDirector()->convertToGL(m_CurTouch);
    
    m_AimLocation.x = m_InitLocation.x + m_CurTouch.x - m_InitTouch.x;
    m_AimLocation.y = m_InitLocation.y + m_CurTouch.y - m_InitTouch.y;
}

void PlayerFighterSprite::touchesEnded(CCSet *touches, CCEvent *event)
{
    m_iTouches--;
    if (1==m_iTouches)
    {
        
    }
}
